﻿using System.IO;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using System.Text;
using System.Threading;

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Formatters;
using Microsoft.AspNetCore.WebUtilities;
using Microsoft.Extensions.Logging;
using System;
using BusinessEntity;
using NLog;
using LogLevel = NLog.LogLevel;
using System.Collections.Generic;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using learun.util;
using BusinessRule;
using System.Configuration;
using Microsoft.Extensions.Configuration;

namespace Assets.API
{
    public class RequestResponseLog
    {
        public string Url { get; internal set; }
        public Dictionary<string, string> Headers { get; internal set; }
        public string Method { get; internal set; }
        public DateTime ExcuteStartTime { get; internal set; }
        public string RequestBody { get; internal set; }
        public string ResponseBody { get; internal set; }
        public DateTime ExcuteEndTime { get; internal set; }

        public string ToJson()
        { 
            var timeConverter = new IsoDateTimeConverter { DateTimeFormat = "yyyy-MM-dd HH:mm:ss" };
            return JsonConvert.SerializeObject(this, timeConverter);
        }
    }

    public class ResponseLogMiddleware
    {
        private readonly RequestDelegate _next;
        private RequestResponseLog _logInfo;
        internal Logger _logger = LogManager.GetCurrentClassLogger();
         
        public ResponseLogMiddleware(RequestDelegate next, IConfiguration configuration)
        {
            _next = next;

            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        public async Task Invoke(HttpContext context)
        {
            _logger.Log(LogLevel.Trace, "**************************开始*********************************");

            _logInfo = new RequestResponseLog();

            HttpRequest request = context.Request;
            _logInfo.Url = request.Path.ToString();
            _logInfo.Headers = request.Headers.ToDictionary(k => k.Key, v => string.Join(";", v.Value.ToList()));
            _logInfo.Method = request.Method;
            _logInfo.ExcuteStartTime = DateTime.Now;

            //获取request.Body内容
            if (request.Method.ToLower().Equals("post"))
            {

                request.EnableBuffering(); //启用倒带功能，就可以让 Request.Body 可以再次读取

                //Stream stream = request.Body;
                //byte[] buffer = new byte[request.ContentLength.Value];
                //stream.Read(buffer, 0, buffer.Length);
                //_logInfo.RequestBody = Encoding.UTF8.GetString(buffer);
                //request.Body.Position = 0;

                request.Body.Seek(0, SeekOrigin.Begin);
                var sr = new StreamReader(request.Body);

                //sr.ReadToEnd(); 同步读取
                //这里必须换成 异步读取才行
                string json = sr.ReadToEndAsync().Result; 

                _logInfo.RequestBody = json;

                request.Body.Seek(0, SeekOrigin.Begin);

            }
            else if (request.Method.ToLower().Equals("get"))
            {
                _logInfo.RequestBody = request.QueryString.Value;
            }

            //获取Response.Body内容
            var originalBodyStream = context.Response.Body;

            using (var responseBody = new MemoryStream())
            {
                context.Response.Body = responseBody;

                await _next(context);

                _logInfo.ResponseBody = await FormatResponse(context.Response);
                _logInfo.ExcuteEndTime = DateTime.Now;



                if (_logInfo.Url != "/swagger/v1/swagger.json")
                    _logger.Log(LogLevel.Trace, $"VisitLog: {_logInfo.ToJson()}");

                _logger.Log(LogLevel.Trace, "**************************完成*********************************");

                //string WriteDBLog = ConfigHelper.GetAppSettings("ServerOp:WriteLogDB");

                //if (WriteDBLog == "1"&& context.Request.Path != "/swagger/v1/swagger.json")
                //{
                //    LogEntity logEntity = new LogEntity();
                //    logEntity.F_CategoryId = 4;
                //    logEntity.F_OperateTypeId = ((int)OperationType.Visit).ToString();
                //    logEntity.F_OperateType = EnumAttribute.GetDescription(OperationType.Visit);
                //    logEntity.F_OperateAccount = ContextHelper.GetItem("userName") as string;
                //    logEntity.F_OperateUserId = ContextHelper.GetItem("userId") as string;
                //    logEntity.F_Module = context.Request.Path;
                //    logEntity.F_IPAddress = context.Request.HttpContext.Connection.RemoteIpAddress.ToString();
                //    logEntity.F_ExecuteResult = -1;
                //    logEntity.F_ExecuteResultJson = _logInfo.ToJson();
                //    LogRule.Write(logEntity).GetAwaiter().GetResult();
                //}

                await responseBody.CopyToAsync(originalBodyStream);
            }
        }

        private async Task<string> FormatResponse(HttpResponse response)
        {
            response.Body.Seek(0, SeekOrigin.Begin);
            var text = await new StreamReader(response.Body).ReadToEndAsync();
            response.Body.Seek(0, SeekOrigin.Begin);

            return text;
        }
    }

}